/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2014-2021.
 * Description: idump signal
 * Author: nixiaoming
 * Create: 2014-6-18
 */

#ifndef _KERNEL_IDUMP_SIGNAL_C
#define _KERNEL_IDUMP_SIGNAL_C

#ifdef CONFIG_RTOS_IDUMP
#include <linux/idump_debug.h>
#include <linux/rtos_mm_types.h>
#include <linux/binfmts.h>
#include <linux/coredump.h>
#include <linux/signal.h>
#include <linux/mmap_lock.h>
#include <linux/spinlock.h>

void do_idump_stop(void)
{
	struct mm_struct *mm = current->mm;
	struct rtos_mm_struct *rtos_mm = mm_to_rtos_mm(mm);
	struct core_state *idump_core_state = NULL;
	struct core_thread self;
	long save = current->state;

	spin_unlock_irq(&current->sighand->siglock);

	mmap_read_lock(mm);
	idump_core_state = rtos_mm->idump.core_state;
	if (idump_core_state == NULL) {
		mmap_read_unlock(mm);
		return;
	}

	self.task = current;
	self.next = xchg(&idump_core_state->dumper.next, &self);

	/*
	 * Implies mb(), the result of xchg() must be visible
	 * to idump_core_state->dumper.
	 */
	if (atomic_dec_and_test(&idump_core_state->nr_threads))
		complete(&idump_core_state->startup);

	mmap_read_unlock(mm);

	for (;;) {
		set_special_state(__TASK_STOPPED);
		if (!self.task)
			break;
		schedule();
	}
	set_current_state(save);

	return;
}

#endif
#endif
